home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
WOW! 2
/
WOW - Vol 2.iso
/
pd_share
/
dfue
/
ka9qst
/
ka9q_src
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-16
|
20KB
|
862 lines
/* Main network program - provides both client and server functions */
#define HOSTNAMELEN 32 /* changed from 16 by Bdale 860812 */
extern char startup[]; /* File to read startup commands from */
#include <stdio.h>
#include "config.h"
#include "global.h"
#include "mbuf.h"
#include "netuser.h"
#include "timer.h"
#include "icmp.h"
#include "iface.h"
#include "ip.h"
#include "tcp.h"
#include "ax25.h"
#include "remote.h"
#include "netrom.h"
#include "ftp.h"
#include "telnet.h"
#include "session.h"
#include "cmdparse.h"
#ifdef UNIX /* BSD or SYS5 */
#include "unix.h"
#endif
#ifdef AMIGA
#include "amiga.h"
#endif
#ifdef MAC
#include "mac.h"
#endif
#ifdef MSDOS
#include "pc.h"
#endif
#ifdef ATARI_ST
#include "st.h"
#endif
#ifdef LATTICE
extern long _MNEED; /* reserve memory for child process (shell) */
long _MNEED = 100000; /* plucked out of thin air */
extern long _32K;
long _32K = 0x8000; /* keep GST Linker happy */
#endif
#ifdef MWC
long _stksize = 0x40000L; /* 256K oughta be enough... */
#endif
#ifdef TRACE
#include "trace.h"
/* Dummy structure for loopback tracing */
struct interface loopback = { NULLIF, "loopback" };
#endif
extern struct interface *ifaces;
extern char version[];
extern char implementation[]; /* DG2KK */
extern struct mbuf *loopq;
int ttyflow; /* NEW!!!!!!!! DG2KK */
int mode;
FILE *logfp;
char badhost[] = "Unknown host %s\n";
char hostname[HOSTNAMELEN];
unsigned nsessions = NSESSIONS;
int32 resolve();
int16 lport = 1001;
char prompt[] = "net> ";
char nospace[] = "No space!!\n"; /* Generic malloc fail message */
#if (!MSDOS && !ATARI_ST) /* PC/Atari uses F-10 key always */
static char escape = 0x1d; /* default escape character is ^] */
#endif
/* Command lookup and branch table */
int go(),doax25(),cmdmode(),doconnect(),dotelnet(),doexit(),doclose(),
dohostname(),doreset(),dotcp(),dotrace(),doescape(),dohelp(),
doroute(),doecho(),dolog(),doip(),doetherstat(),
memstat(),doarp(),dosession(),doftp(),dostart(),dostop(),doattach(),
dosmtp(),doudp(),doparam(),doeol(),dohapnstat(),doremote(),
doegstat(),dodump(),dorecord(),doupload(),dokick(),domode(),doshell(),
dodir(),docd(),doatstat(),doping(),donetrom(),donrstat(),dotype();
static struct cmds cmds[] = {
/* The "go" command must be first */
"", go, 0, NULLCHAR, NULLCHAR,
"!", doshell, 0, NULLCHAR, NULLCHAR,
#if (MAC && APPLETALK)
"applestat", doatstat, 0, NULLCHAR, NULLCHAR,
#endif
#if (AX25 || ETHER || APPLETALK)
"arp", doarp, 0, NULLCHAR, NULLCHAR,
#endif
#ifdef AX25
"ax25", doax25, 0, NULLCHAR, NULLCHAR,
#endif
"attach", doattach, 2,
"attach <hardware> <hw specific options>", NULLCHAR,
/* This one is out of alpabetical order to allow abbreviation to "c" */
#ifdef AX25
"connect", doconnect, 3,"connect interface callsign [digipeaters]",
NULLCHAR,
#endif
#ifndef UNIX /* BSD or SYS5 */
"cd", docd, 0, NULLCHAR, NULLCHAR,
#endif
"close", doclose, 0, NULLCHAR, NULLCHAR,
"disconnect", doclose, 0, NULLCHAR, NULLCHAR,
"dir", dodir, 0, NULLCHAR, NULLCHAR,
#ifdef EAGLE
"eaglestat", doegstat, 0, NULLCHAR, NULLCHAR,
#endif
"echo", doecho, 0, NULLCHAR, "echo [refuse|accept]",
"eol", doeol, 0, NULLCHAR,
"eol options: unix, standard",
#if (!MSDOS && !ATARI_ST)
"escape", doescape, 0, NULLCHAR, NULLCHAR,
#endif
#ifdef PC_EC
"etherstat", doetherstat, 0, NULLCHAR, NULLCHAR,
#endif PC_EC
"exit", doexit, 0, NULLCHAR, NULLCHAR,
"ftp", doftp, 2, "ftp <address>", NULLCHAR,
#ifdef HAPN
"hapnstat", dohapnstat, 0, NULLCHAR, NULLCHAR,
#endif HAPN
"help", dohelp, 0, NULLCHAR, NULLCHAR,
"hostname", dohostname, 0, NULLCHAR, NULLCHAR,
"kick", dokick, 0, NULLCHAR, NULLCHAR,
"log", dolog, 0, NULLCHAR, NULLCHAR,
"ip", doip, 0, NULLCHAR, NULLCHAR,
"memstat", memstat, 0, NULLCHAR, NULLCHAR,
#ifdef AX25
"mode", domode, 2, "mode <interface>", NULLCHAR,
"netrom", donetrom, 0, NULLCHAR, NULLCHAR,
"nrstat", donrstat, 0, NULLCHAR, NULLCHAR,
#endif
"param", doparam, 2, "param <interface>", NULLCHAR,
"ping", doping, 0, NULLCHAR, NULLCHAR,
#ifndef UNIX /* BSD or SYS5 */
"pwd", docd, 0, NULLCHAR, NULLCHAR,
#endif
"record", dorecord, 0, NULLCHAR, NULLCHAR,
"remote", doremote, 4, "remote <address> <port> <command>",
NULLCHAR,
"reset", doreset, 0, NULLCHAR, NULLCHAR,
"route", doroute, 0, NULLCHAR, NULLCHAR,
"session", dosession, 0, NULLCHAR, NULLCHAR,
"shell", doshell, 0, NULLCHAR, NULLCHAR,
"smtp", dosmtp, 0, NULLCHAR, NULLCHAR,
#ifdef SERVERS
"start", dostart, 2, "start <servername>",NULLCHAR,
"stop", dostop, 2, "stop <servername>", NULLCHAR,
#endif
"tcp", dotcp, 0, NULLCHAR, NULLCHAR,
"telnet", dotelnet, 2, "telnet <address>", NULLCHAR,
#ifdef TRACE
"trace", dotrace, 0, NULLCHAR, NULLCHAR,
#endif
"type", dotype, 0, NULLCHAR, NULLCHAR,
"udp", doudp, 0, NULLCHAR, NULLCHAR,
"upload", doupload, 0, NULLCHAR, NULLCHAR,
"?", dohelp, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0,
"Unknown command; type \"?\" for list", NULLCHAR,
};
#ifdef SERVERS
/* "start" and "stop" subcommands */
int ftp_start(),smtp_start(),discard_start(),echo_start(),telnet_start();
int tnc_start(), rem_start();
static struct cmds startcmds[] = {
"discard", discard_start, 0, NULLCHAR, NULLCHAR,
"echo", echo_start, 0, NULLCHAR, NULLCHAR,
"ftp", ftp_start, 0, NULLCHAR, NULLCHAR,
"remote", rem_start, 0, NULLCHAR, NULLCHAR,
"smtp", smtp_start, 0, NULLCHAR, NULLCHAR,
"telnet", telnet_start, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0,
"start options: discard, echo, ftp, remote, smtp, telnet",
NULLCHAR,
};
int ftp_stop(),smtp_stop(),echo_stop(),discard_stop(),telnet_stop(),
rem_stop();
static struct cmds stopcmds[] = {
"discard", discard_stop, 0, NULLCHAR, NULLCHAR,
"echo", echo_stop, 0, NULLCHAR, NULLCHAR,
"ftp", ftp_stop, 0, NULLCHAR, NULLCHAR,
"remote", rem_stop, 0, NULLCHAR, NULLCHAR,
"smtp", smtp_stop, 0, NULLCHAR, NULLCHAR,
"telnet", telnet_stop, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0,
"stop options: discard, echo, ftp, remote, smtp, telnet",
NULLCHAR,
};
#endif
void
keep_things_going()
{
void check_time();
struct interface *ifp;
struct mbuf *bp;
/* Service the loopback queue */
if((bp = dequeue(&loopq)) != NULLBUF){
/* struct ip ip; */
#ifdef TRACE
dump(&loopback,IF_TRACE_IN,TRACE_IP,bp);
#endif
/* Extract IP header */
/* ntohip(&ip,&bp);
ip_recv(&ip,bp,0); */
ip_recv(bp,0);
}
/* Service the interfaces */
for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next){
if(ifp->recv != NULLFP)
(*ifp->recv)(ifp);
}
/* Service the clock if it has ticked */
check_time();
#ifdef MSDOS
/* Tell Doubledos to let the other task run for awhile.
* If Doubledos isn't active, this is a no-op.
*/
giveup();
#else
/* Wait until interrupt, then do it all over again */
eihalt();
#endif
}
main(argc,argv)
int argc;
char *argv[];
{
static char inbuf[BUFSIZ]; /* keep it off the stack */
int c;
char *ttybuf,*fgets();
int16 cnt;
int ttydriv();
int cmdparse();
void check_time();
FILE *fp;
ioinit();
#if (!UNIX && !AMIGA && !MAC && !ATARI_ST)
chktasker();
#endif
#ifdef MSDOS
printf("KA9Q Internet Protocol Package, v%s DS = %x\n",version,
getds());
#else
printf("KA9Q Internet Protocol Package, v%s\n",version);
#endif
/* printf("%s\n",implementation); */ /* DG2KK */
printf("Copyright 1988 by Phil Karn, KA9Q\n");
sessions = (struct session *)calloc(nsessions,sizeof(struct session));
if(argc > 1){
/* Read startup file named on command line */
fp = fopen(argv[1],"r");
} else {
fp = fopen(startup,"r");
}
if(fp != NULLFILE){
while(fgets(inbuf,BUFSIZ,fp) != NULLCHAR){
cmdparse(cmds,inbuf);
}
fclose(fp);
}
cmdmode();
/* Main commutator loop */
for(;;){
/* Process any keyboard input */
while((c = kbread()) != -1){
#if (MSDOS || ATARI_ST)
/* c == -2 means the command escape key (F10) */
if(c == -2){
if(mode != CMD_MODE){
printf("\n");
cmdmode();
}
continue;
}
#endif
#ifdef SYS5
if(c == escape && escape != 0){
if(mode != CMD_MODE){
printf("\r\n");
cmdmode();
}
continue;
}
#endif /* SYS5 */
/* ----------------------------(DG2KK)------------------------------- */
#ifndef FLOW
if((cnt = ttydriv(c,&ttybuf)) == 0)
continue;
#else
cnt = ttydriv(c,&ttybuf);
if (cnt == 0) { /* should be != 0 */
ttyflow = 0; /* stop output to screen */
} else {
ttyflow = 1; /* restart output */
if(mode != CMD_MODE)
go(); /* display pending chars */
}
if (cnt == 0)
continue;
#endif FLOW
/* ------------------------------------------------------------------ */
switch(mode){
case CMD_MODE:
(void)cmdparse(cmds,ttybuf);
fflush(stdout);
break;
case CONV_MODE:
#if (!MSDOS && !ATARI_ST)
if(ttybuf[0] == escape && escape != 0){
printf("\n");
cmdmode();
} else
#endif
if(current->parse != NULLFP)
(*current->parse)(ttybuf,cnt);
break;
}
if(mode == CMD_MODE){
printf(prompt);
fflush(stdout);
}
}
keep_things_going();
}
}
/* Standard commands called from main */
/* Enter command mode */
int
cmdmode()
{
if(mode != CMD_MODE){
mode = CMD_MODE;
cooked();
printf(prompt);
fflush(stdout);
echo();
}
return 0;
}
static
doexit()
{
if(logfp != NULLFILE)
fclose(logfp);
iostop();
exit(0);
}
static
dohostname(argc,argv)
int argc;
char *argv[];
{
char *strncpy();
if(argc < 2)
printf("%s\n",hostname);
else
strncpy(hostname,argv[1],HOSTNAMELEN);
return 0;
}
static
int
dolog(argc,argv)
int argc;
char *argv[];
{
char *strncpy();
static char logname[15];
if(argc < 2){
if(logfp)
printf("Logging to %s\n",logname);
else
printf("Logging off\n");
return 0;
}
if(logfp){
fclose(logfp);
logfp = NULLFILE;
}
if(strcmp(argv[1],"stop") != 0){
strncpy(logname,argv[1],15);
logfp = fopen(logname,"a+");
}
return 0;
}
static
int
dohelp()
{
register struct cmds *cmdp;
int i,j;
printf("Main commands:\n");
for(i=0,cmdp = cmds;cmdp->name != NULL;cmdp++,i++){
printf("%s",cmdp->name);
if((i % 4) == 3)
printf("\n");
else {
for(j=strlen(cmdp->name);j < 16; j++)
putchar(' ');
}
}
if((i % 4) != 0)
printf("\n");
return 0;
}
doecho(argc,argv)
int argc;
char *argv[];
{
extern int refuse_echo;
if(argc < 2){
if(refuse_echo)
printf("Refuse\n");
else
printf("Accept\n");
} else {
if(argv[1][0] == 'r')
refuse_echo = 1;
else if(argv[1][0] == 'a')
refuse_echo = 0;
else
return -1;
}
return 0;
}
/* set for unix end of line for remote echo mode telnet */
doeol(argc,argv)
int argc;
char *argv[];
{
extern int unix_line_mode;
if(argc < 2){
if(unix_line_mode)
printf("Unix\n");
else
printf("Standard\n");
} else {
if(strcmp(argv[1],"unix") == 0)
unix_line_mode = 1;
else if(strcmp(argv[1],"standard") == 0)
unix_line_mode = 0;
else {
return -1;
}
}
return 0;
}
/* Attach an interface
* Syntax: attach <hw type> <I/O address> <vector> <mode> <label> <bufsize> [<speed>]
*/
doattach(argc,argv)
int argc;
char *argv[];
{
extern struct cmds attab[];
return subcmd(attab,argc,argv);
}
/* Manipulate I/O device parameters */
doparam(argc,argv)
int argc;
char *argv[];
{
register struct interface *ifp;
for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){
if(strcmp(argv[1],ifp->name) == 0)
break;
}
if(ifp == NULLIF){
printf("Interface \"%s\" unknown\n",argv[1]);
return 1;
}
if(ifp->ioctl == NULLFP){
printf("Not supported\n");
return 1;
}
/* Pass rest of args to device-specific code */
return (*ifp->ioctl)(ifp,argc-2,argv+2);
}
/* -------------------------------------------------------- */
/* Log messages of the form
* Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
*/
/*VARARGS2*/
log(tcb,fmt,arg1,arg2,arg3,arg4)
struct tcb *tcb;
char *fmt;
int arg1,arg2,arg3,arg4;
{
char *cp;
long t;
int fd;
if(logfp == NULLFILE)
return;
time(&t);
cp = ctime(&t);
rip(cp);
/* log events which don't have an IP address (AX.25 connects etc) */
if (tcb != NULLTCB) {
fprintf(logfp,"%s %s - ",cp,psocket(&tcb->conn.remote));
} else {
fprintf(logfp,"%s - ",cp);
}
fprintf(logfp,fmt,arg1,arg2,arg3,arg4);
fprintf(logfp,"\n");
fflush(logfp);
#if ( MSDOS || ATARI_ST )
/* MS-DOS doesn't really flush files until they're closed */
fd = fileno(logfp);
if((fd = dup(fd)) != -1)
close(fd);
#endif
}
/* ------------------------------------------------------------------ */
/* Configuration-dependent code */
/* List of supported hardware devices */
int ec_attach(),asy_attach(),pc_attach(),eg_attach(),hapn_attach(),at_attach(),
nr_attach();
struct cmds attab[] = {
#ifdef PC_EC
/* 3-Com Ethernet interface */
"3c500", ec_attach, 7,
"attach 3c500 <address> <vector> arpa <label> <buffers> <mtu>",
"Could not attach 3c500",
#endif
#ifdef SLIP
/* Ordinary PC asynchronous adaptor */
"asy", asy_attach, 8,
#ifndef SLFP
"attach asy <address> <vector> slip|ax25 <label> <buffers> <mtu> <speed>",
#else
"attach asy <address> <vector> slip|ax25|slfp <label> <buffers> <mtu> <speed>",
#endif
"Could not attach asy",
#endif
#ifdef PC100
/* PACCOMM PC-100 8530 HDLC adaptor */
"pc100", pc_attach, 8,
"attach pc100 <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
"Could not attach pc100",
#endif
#ifdef EAGLE
/* EAGLE RS-232C 8530 HDLC adaptor */
"eagle", eg_attach, 8,
"attach eagle <address> <vector> ax25 <label> <buffers> <mtu> <speed>",
"Could not attach eagle",
#endif
#ifdef HAPN
/* Hamilton Area Packet Radio (HAPN) 8273 HDLC adaptor */
"hapn", hapn_attach, 8,
"attach hapn <address> <vector> ax25 <label> <rx bufsize> <mtu> csma|full",
"Could not attach hapn",
#endif
#ifdef APPLETALK
/* Macintosh AppleTalk */
"0", at_attach, 7,
"attach 0 <protocol type> <device> arpa <label> <rx bufsize> <mtu>",
"Could not attach Appletalk",
#endif
#ifdef AX25
/* Fake NET/ROM interface */
"netrom", nr_attach, 1,
"attach netrom",
"Could not attach netrom",
#endif
NULLCHAR, NULLFP, 0,
"Unknown device",
NULLCHAR,
};
/* Protocol tracing function pointers */
#ifdef TRACE
int ax25_dump(),ether_dump(),ip_dump(),at_dump(),slfp_dump();
int (*tracef[])() = {
#ifdef AX25
ax25_dump,
#else
NULLFP,
#endif
#ifdef ETHER
ether_dump,
#else
NULLFP,
#endif
ip_dump,
#ifdef APPLETALK
at_dump,
#else
NULLFP,
#endif
#ifdef SLFP
slfp_dump,
#else
NULLFP,
#endif
};
#else
int (*tracef[])() = { NULLFP }; /* No tracing at all */
dump(interface,direction,type,bp)
struct interface *interface;
int direction;
unsigned type;
struct mbuf *bp;
{
}
#endif
#ifdef AX25
/* Set up a SLIP link to use AX.25 */
kiss_attach(if_asy,srecv)
struct interface *if_asy;
int (**srecv)();
{
int kiss_ioctl(),ax_send(),ax_output(),kiss_raw(),kiss_recv();
axarp();
if(mycall.call[0] == '\0'){
printf("set mycall first\n");
free((char *)if_asy);
return -1;
}
if_asy->ioctl = kiss_ioctl;
if_asy->send = ax_send;
if_asy->output = ax_output;
if_asy->raw = kiss_raw;
if(if_asy->hwaddr == NULLCHAR)
if_asy->hwaddr = malloc(sizeof(mycall));
memcpy(if_asy->hwaddr,(char *)&mycall,sizeof(mycall));
*srecv = kiss_recv;
return 0;
}
/* Set up a net/rom serial interface */
nrs_attach(if_asy,call)
struct interface *if_asy;
char *call ;
{
struct ax25_addr addr ;
int ax_send(),ax_output(),nrs_raw(),nrs_recv(),asy_ioctl();
if (call == NULLCHAR) { /* no call supplied? */
if(mycall.call[0] == '\0'){ /* try to use default */
printf("set mycall first or specify in attach statement\n");
return -1;
}
else
addr = mycall ;
}
else { /* callsign supplied on attach line */
if (setcall(&addr,call) == -1) {
printf ("bad callsign on attach line\n") ;
return -1 ;
}
}
if_asy->flags |= CONNECT_MODE; /* DG2KK: was: IF_AX25 */
if_asy->recv = nrs_recv ;
if_asy->ioctl = asy_ioctl ;
if_asy->send = ax_send;
if_asy->output = ax_output;
if_asy->raw = nrs_raw;
if(if_asy->hwaddr == NULLCHAR)
if_asy->hwaddr = malloc(sizeof(addr));
memcpy(if_asy->hwaddr,(char *)&addr,sizeof(addr));
return 0;
}
/* Display or set IP interface control flags */
domode(argc,argv)
int argc;
char *argv[];
{
register struct interface *ifp;
for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){
if(strcmp(argv[1],ifp->name) == 0)
break;
}
if(ifp == NULLIF){
printf("Interface \"%s\" unknown\n",argv[1]);
return 1;
}
if(argc < 3){
printf("%s: %s\n",ifp->name,
(ifp->flags & CONNECT_MODE) ? "VC mode" : "Datagram mode");
return 0;
}
switch(argv[2][0]){
case 'v':
case 'c':
case 'V':
case 'C':
ifp->flags = CONNECT_MODE;
break;
case 'd':
case 'D':
ifp->flags = DATAGRAM_MODE;
break;
default:
printf("Usage: %s [vc | datagram]\n",argv[0]);
return 1;
}
return 0;
}
#endif
#ifdef SERVERS
dostart(argc,argv)
int argc;
char *argv[];
{
return subcmd(startcmds,argc,argv);
}
dostop(argc,argv)
int argc;
char *argv[];
{
return subcmd(stopcmds,argc,argv);
}
#endif SERVERS
#ifdef TRACE
static
int
dotrace(argc,argv)
int argc;
char *argv[];
{
struct interface *ifp;
if(argc < 2){
showtrace(&loopback);
for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
showtrace(ifp);
return 0;
}
if(strcmp("loopback",argv[1]) == 0)
ifp = &loopback;
else
for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
if(strcmp(ifp->name,argv[1]) == 0)
break;
if(ifp == NULLIF){
printf("Interface %s unknown\n",argv[1]);
return 1;
}
if(argc >= 3)
ifp->trace = htoi(argv[2]);
showtrace(ifp);
return 0;
}
/* Display the trace flags for a particular interface */
static
showtrace(ifp)
register struct interface *ifp;
{
if(ifp == NULLIF)
return;
printf("%s:",ifp->name);
if(ifp->trace & (IF_TRACE_IN | IF_TRACE_OUT)){
if(ifp->trace & IF_TRACE_IN)
printf(" input");
if(ifp->trace & IF_TRACE_OUT)
printf(" output");
if(ifp->trace & IF_TRACE_HEX)
printf(" (Hex/ASCII dump)");
else if(ifp->trace & IF_TRACE_ASCII)
printf(" (ASCII dump)");
else
printf(" (headers only)");
printf("\n");
} else
printf(" tracing off\n");
fflush(stdout);
}
#endif
#if (!MSDOS && !ATARI_ST)
static
int
doescape(argc,argv)
int argc;
char *argv[];
{
if(argc < 2)
printf("0x%x\n",escape);
else
escape = *argv[1];
return 0;
}
#endif
static
doremote(argc,argv)
int argc;
char *argv[];
{
struct socket fsock,lsock;
struct mbuf *bp;
lsock.address = ip_addr;
fsock.address = resolve(argv[1]);
lsock.port = fsock.port = atoi(argv[2]);
bp = alloc_mbuf(1);
if(strcmp(argv[3],"reset") == 0){
*bp->data = SYS_RESET;
} else if(strcmp(argv[3],"exit") == 0){
*bp->data = SYS_EXIT;
} else {
printf("Unknown command %s\n",argv[3]);
return 1;
}
bp->cnt = 1;
send_udp(&lsock,&fsock,0,0,bp,0,0,0);
return 0;
}